<template>
  <div ref="wrapper" class="inline-edit" @click.stop="handleClick">
    <el-input v-if="isEditing" ref="inputRef" v-model="innerValue" placeholder="文本不能为空" />
    <slot v-else :text="innerValue" class="input">
      <span>{{ innerValue }}</span>
    </slot>
  </div>
</template>

<script lang="ts" setup>
import useKeyPress from '@/hooks/useKeyPress'
import useClickOutside from '@/hooks/useClickOutside'

const props = withDefaults(defineProps<{ value: string }>(), { value: '' })
const innerValue = ref(props.value)
const emits = defineEmits(['change'])

const wrapper = ref<null | HTMLElement>(null)
const inputRef = ref<null | HTMLInputElement>(null)
const isEditing = ref(false)

const isClickOutside = useClickOutside(wrapper)

let cachedOldValue = ''

watch(
  () => props.value,
  newValue => {
    innerValue.value = newValue
  }
)

watch(isEditing, async isEditing => {
  if (isEditing) {
    cachedOldValue = innerValue.value
    await nextTick()
    if (inputRef.value) {
      inputRef.value.focus()
    }
  }
})

watch(isClickOutside, isOutside => {
  if (isOutside && isEditing.value) {
    isEditing.value = false
    emits('change', innerValue.value)
  }
  isClickOutside.value = false
})

useKeyPress('Enter', () => {
  if (isEditing.value) {
    isEditing.value = false
    emits('change', innerValue.value)
  }
})

useKeyPress('Escape', () => {
  if (isEditing.value) {
    isEditing.value = false
    innerValue.value = cachedOldValue
  }
})

const handleClick = () => {
  isEditing.value = true
}
</script>
<style lang="scss" scoped>
.inline-edit {
  cursor: pointer;
}
.input.input-error {
  border: 1px solid #f5222d;
}
.input.input-error:focus {
  border-color: #f5222d;
}
.input.input-error::placeholder {
  color: #f5222d;
}
</style>
